1. /* sdfrsqrt.cpp by K.Tsuru */
  2. // function ID 3006 DARDIX only
  3. /***********************************************************************
  4. SDouble class
  5. It provides 1/sqrt(x) using Newton's method i.e. by solving the equation
  6. x - 1/(y^2) = 0.
  7. [Algorism]
  8. Taking w=x*100^p the value of 'p' is chosen to satisfy a condition 0.01<w<1.
  9. The initial value is taken as y(0)=1/sqrt(w)(calculated by double).
  10. It repeats
  11. y(n+1)=y(n)+dy where dy=0.5*y(n)(1-wy(n)^2).
  12. Here 'y' has a value y = 1/(sqrt(x*100^p))= 1/(sqrt(x)*10^p), then considering
  13. 1/sqrt(x) = y*10^p, it multiplies 'y' by 10^p at last.
  14. If the doubling effective figures method is used it becomes a few times faster.
  15. It is very efficient as
  16. y(n) = 0.abcd ..... efgh ijkl
  17. dy = 0.0000 ..... 0000 EFGH IJKL ....
  18. the non-zero part of 'dy' overlaps with that of y(n) by a few figures.
  19. At last it adds a correction such as
  20. delta = one - w*(y*y);
  21. if(!delta.IsHidden()) y = y + y*DsDiv(delta, 2);
  22. **2017/08/06**** Sqrt(0.231106....) in 100000000(digits) ****** use SinTabele ******
  23. 2nd convergence
  24. 100000000 53.844(sec) 0.0 ????
  25. 125.483 -2.0 e-100000032
  26. 125.527 0.0
  27. 4th convergence
  28. 100000000 136.265(sec) 0.0 slower
  29. 251.858 1.0 e-100000032
  30. ***********************************************************************/
  31. #ifndef SN_H
  32. #include "sn.h"
  33. #endif
  34. //Multiplying by 4^n it reduces as 0.25<w<1, the precision is nearly the same.
  35. #define reduceGT025 0 //using 0.25 < w < 1.0
  36. #define USES_2ND_CONV_RSQRT 1 // 2nd convergence=======================
  37. static const char* const func = "RecSqrt";
  38. SDouble RecSqrt(const SDouble& x){
  39. if(x.Type() != x.REAL) x.SetError(x.RADIX_ERR, func, 3006);
  40. RealSize C;
  41. uint max_sz = x.MaxSize();
  42. SDouble w(x);
  43. double w0;
  44. if( x.Sign() == 0 ) x.SetError(x.DIVIDED_BY_ZERO, func, 3006);
  45. else if( x.Sign() < 0 ) x.SetError(x.DOMAIN_ERR, func, 3006);
  46. if(x.IsOne()) return ONE; // x = 1.0
  47. int pow10 = w.NetRdxExp()*DFIGURES/2; // DFIGURES is an even number.
  48. w.MultPowRdx( -w.NetRdxExp()); //Here 0.0001(=1/DRADIX) <= w < 1.0.
  49. /* setting the initial value 'y0'*/
  50. w0 = doubleD(w); // 0.0001 <= w0 < 1.0
  51. #ifndef NDEBUG
  52. assert( (w0 > 0.0) && (w0 <= 1.0 + DBL_EPSILON) );
  53. #endif
  54. ulong m = 1uL;
  55. if(w0 < 0.01){ // 0.01 <= w0 < 1.0
  56. w0 *= 100.0; m *= 100uL; pow10--;
  57. }
  58. #if reduceGT025
  59. ulong mpow2 = 1uL;
  60. while(w0 < 0.25){
  61. w0 *= 4.0; m *= 4uL; mpow2 *= 2uL;
  62. }
  63. #endif
  64. if(m > 1uL) w = DsMult(w, m);
  65. //It enters into the irreducible size mode.
  66. SDouble y(x.REAL, max_sz), delta(x.REAL, max_sz);
  67. y = 1./sqrt(w0); // 'y' has about DOUBLE_FIG(=15) figures.
  68. /****************************/
  69. // c:counter, itrmax:upper limit of iteration
  70. int c = 0, itrmax = howpow2( (DFIGURES*max_sz)/DOUBLE_FIG+1 ) +6;
  71. uint ef = (DOUBLE_FIG*2u)/DFIGURES, fig = C.EffFigures();
  72. bool fullPrec = false; //calclation is done in full precision or not
  73. delta = w0 - w;
  74. if( delta.Sign() ){
  75. // If w0 is very close to double value, higher precision is necessary.
  76. ef = max( ef, 2u*(uint)abs( delta.NetRdxExp()) );
  77. }
  78. //It takes into the fixed point mode.
  79. y.FixedPoint(y.RdxExp());
  80. if(ef > fig) ef = fig;
  81. do{
  82. if((ef = C.SetEffFig(ef)) >= fig) fullPrec = true;
  83. #if USES_2ND_CONV_RSQRT // 2nd convergence=======================
  84. // faster than dev = w*y*y in DDMult()
  85. delta = y*y;
  86. delta *= w;
  87. delta = ONE - delta;
  88. #ifndef NDEBUG
  89. if(delta.FigureSize() != y.FigureSize()){
  90. fprintf(stderr, "%u %u\n", delta.FigureSize(), y.FigureSize());
  91. }
  92. assert(delta.FigureSize() == y.FigureSize());
  93. #endif
  94. delta = DDiv2(delta);// delta /= 2
  95. delta = y*delta;
  96. y += delta; //Non-zero figures overlap by a few figures.
  97. c++;
  98. ef *= 2;
  99. if(ef >= fig) ef = fig;
  100. C.SetEffFig(0);
  101. } while( ( !delta.IsHidden() && (c < itrmax) ) || !fullPrec );
  102. #else // 4th convergence=======================
  103. //cout << " Using 4th convergence " << endl;
  104. SDouble h = ONE - w*(y*y);
  105. delta = DDiv2(h) + 0.375*(h*h);
  106. y *= ONE + delta;
  107. c++;
  108. ef *= 4;
  109. if(ef >= fig) ef = fig;
  110. C.SetEffFig(0);
  111. //cout << "c= " << c << " delta.NetRdxExp() =" << delta.NetRdxExp() << endl;
  112. } while( ( !delta.IsMLT(ONE) && (c < itrmax) ) || !fullPrec );
  113. #endif
  114. //The condition "!delta.IsHidden()" corresponds to see the relative error.
  115. //The condition "c < itrmax" is not necessary but to avoid the endless repeat.
  116. if(c == itrmax) y.SetError(y.FATAL, func, 3006);
  117. y.iterationCount = c;
  118. y.PointFree();
  119. y.Reform(3006);
  120. /*
  121. In order to avoid "Verify" error which is rare, it adds a correction.
  122. It evaluates d = 1-w*y'^2 where y' is an approximate value of 1/sqrt(w).
  123. When d != 0
  124. y' = sqrt((1-d)/w) = y*sqrt(1-d) ( y = 1/sqrt(w) )
  125. y' ~= y*(1-d/2), y ~= y'*(1+d/2).
  126. Then the correction is given by y'*d/2.
  127. */
  128. #if 1
  129. if(y.PreferSpeed() == OFF){
  130. delta = ONE - w*(y*y);
  131. delta = DsDiv(delta, 2); // delta /= 2 "delta" has about one figure.
  132. // delta = (1 - w*y^2)/2
  133. if(delta.Sign()) y += y*delta;
  134. }
  135. #endif
  136. if(y.Verify()){ // check y = 1/sqrt(w) i.e. 1-w*y^2 << 1.0 ?
  137. delta = ONE - w*(y*y);
  138. if(!delta.IsMLT(ONE)){
  139. y.SetError(y.VERIFY, func, 3006);
  140. }
  141. }
  142. if(pow10) y.MultPow10(-pow10);
  143. #if reduceGT025
  144. if(mpow2 > 1uL) return DsMult(y, mpow2);
  145. #endif
  146. return y;
  147. }

sdfrsqrt.cpp : last modifiled at 2017/08/25 15:40:21(5,323 bytes)
created at 2017/10/07 10:22:50
The creation time of this html file is 2017/10/07 11:29:39 (Sat Oct 07 11:29:39 2017).